package cmd

import (
	"context"
	"fmt"
	"os"

	sdk "gitee.com/wx-rdc/secloud-sdk-go/secloud"
	"github.com/antihax/optional"
	"github.com/spf13/cobra"
)

var featureCmd = &cobra.Command{
	Use:   "feature",
	Short: "run feature tests",
	Long:  `demo feature: run all tests for feature`,
	Run: func(cmd *cobra.Command, args []string) {
		runAllTests()
	},
}

func initFeature() {
	rootCmd.AddCommand(featureCmd)
}

func runAllTests() {
	// create api client
	client := sdk.NewAPIClient(sdk.NewConfiguration(API_URL))

	// auth api
	authOpts := &sdk.AuthOpts{
		ClientId:     optional.NewString(CLIENT_ID),
		ClientSecret: optional.NewString(CLIENT_SECRET),
	}
	data, err := client.AuthApi.Token(context.Background(), authOpts)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	accessCtx := context.WithValue(
		context.Background(),
		sdk.ContextAccessToken, data.AccessToken)

	// generateKeyPair
	keyPair, err := client.KmsApi.GenerateKeyPair(accessCtx, nil)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("GenerateKeyPair:\npkey %s\nskey %s\n", keyPair.Pkey, keyPair.Skey)

	// generateKeyPairWithKEK
	generateKeyPairWithKEKOpts := &sdk.GenerateKeyPairWithKEKOpts{
		KekIndex: optional.NewInt(KEK_INDEX),
	}
	keyPairWithKEKResp, err := client.KmsExtApi.GenerateKeyPairWithKEK(accessCtx, generateKeyPairWithKEKOpts)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("ipxIndex: %d\nsignPkey: %s\nsignSkey: %s\nencPkey: %s\nencSkey: %s\n",
		keyPairWithKEKResp.IpxIndex,
		keyPairWithKEKResp.SignPkey,
		keyPairWithKEKResp.SignSkey,
		keyPairWithKEKResp.EncPkey,
		keyPairWithKEKResp.EncSkey,
	)

	for _, deviceUrl := range DEVICE_URLS {
		// importKeyPairWithKEK
		importKeyPairWithKEKOpts := &sdk.ImportKeyPairWithKEKOpts{
			DeviceUrl: optional.NewString(deviceUrl),
			KekIndex:  optional.NewInt(KEK_INDEX),
			IpxIndex:  optional.NewInt(IPX_INDEX),
			SignPkey:  optional.NewString(SIGN_PKEY),
			SignSkey:  optional.NewString(SIGN_SKEY),
			EncPkey:   optional.NewString(ENC_PKEY),
			EncSkey:   optional.NewString(ENC_SKEY),
		}
		importKeyPairWithKEKResp, err := client.KmsExtApi.ImportKeyPairWithKEK(accessCtx, importKeyPairWithKEKOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Printf("ImportKeyPairWithKEK: %s %d\n", deviceUrl, importKeyPairWithKEKResp.Id)
	}

	// generateWorkingKey
	workingKey, err := client.KmsApi.GenerateWorkingKey(accessCtx, nil)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("WorkingKey code: %s\nencKey: %s\n",
		workingKey.Code, workingKey.EncKey)

	// encrypt
	encryptOpts := &sdk.EncryptOpts{
		KeyId: optional.NewString(WORKING_KEY_ID),
		Data:  optional.NewString("abcdefghijklmnopqrstuvwxyz"),
	}
	encryptResp, err := client.CipherApi.Encrypt(accessCtx, encryptOpts)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("Encrypt data: %s\n", encryptResp.EncData)

	// decrypt
	decryptOpts := &sdk.DecryptOpts{
		EncData: optional.NewString(encryptResp.EncData),
	}
	decryptResp, err := client.CipherApi.Decrypt(accessCtx, decryptOpts)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("Decrypt data: %s\n", decryptResp.Data)

	// random
	randomOpts := &sdk.RandomOpts{
		Len: optional.NewInt(16),
	}
	randomResp, err := client.CipherApi.Random(accessCtx, randomOpts)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("Random value: %s\n", randomResp.Data)
}
